/**
   ********************* (C) COPYRIGHT 2021 LionHeart **********************
   * @file         camera.c/h 
   * @brief  
   *
   * @note
   * @history
   *  Version      Data             Author
   *  V1.0.0       2021-10-22 13-17 Yanfubing
   *
    @verbatim
    ========================================================================
    
    ========================================================================
    @endverbatim
************************ (C) COPYRIGHT 2021 LionHeart **********************
*/
#include "camera.h"
#include "main.h"
#include "stdio.h"
#include "adc.h"
#include "usart.h"
#include "gpio.h"
#include "string.h"



extern ADC_HandleTypeDef hadc1;
uint8_t IntegrationTime = 1;
uint16_t Last_CCD_Zhongzhi,Left,Right;
/*************************************************************************
*                         
*
*  函数名称：delay_ms()
*  功能说明：延迟
*  参数说明：
*  函数返回：无
*  备    注：
*************************************************************************/
void delay_us(uint16_t acf)
{
  uint16_t iii=0;
	for(;iii<acf*2;iii++);
}
	
/*************************************************************************
*                         
*
*  函数名称：StartIntegration
*  功能说明：CCD启动程序
*  参数说明：
*  函数返回：无
*  修改时间：2021-10-20
*  备    注：
*************************************************************************/
void StartIntegration(void) {

    unsigned char i;

    SI_SetVal();            /* SI  = 1 */
    SamplingDelay();
    CLK_SetVal();           /* CLK = 1 */
    SamplingDelay();
    SI_ClrVal();            /* SI  = 0 */
    SamplingDelay();
    CLK_ClrVal();           /* CLK = 0 */

    for(i=0; i<127; i++)
    {
    SamplingDelay();
    SamplingDelay();
    CLK_SetVal();       /* CLK = 1 */
    SamplingDelay();
    SamplingDelay();
    CLK_ClrVal();       /* CLK = 0 */
    }
    SamplingDelay();
    SamplingDelay();
    CLK_SetVal();           /* CLK = 1 */
    SamplingDelay();
    SamplingDelay();
    CLK_ClrVal();           /* CLK = 0 */
		
}

/*************************************************************************
*                         
*  函数名称：ImageCapture
*  功能说明：CCD采样程序
*  参数说明：* ImageData   采样数组
*  函数返回：无
*  修改时间：2021-10-20
*  备    注：
*ImageData =  ad_once(ADC1, AD6a, ADC_8bit);
*************************************************************************/
void ImageCapture(uint8_t * ImageData) 
	{
    uint8_t i,n;
	  //uint8_t avger;
	  uint8_t * ImageData1;
    extern uint8_t AtemP ;
    ImageData1=ImageData;
    SI_SetVal();            /* SI  = 1 */
    delay_us(20);
    CLK_SetVal();           /* CLK = 1 */
	  delay_us(20);
    SI_ClrVal();            /* SI  = 0 */
    delay_us(30);
//Delay 10us for sample the first pixel
    for(i = 0; i < 250; i++) {                    //更改250，让CCD的图像看上去比较平滑，
      SamplingDelay();  //200ns                  //把该值改大或者改小达到自己满意的结果。
    }
//Sampling Pixel 1

    *ImageData =  Get_Adc1(&hadc1)>>4;
    ImageData ++ ;
    CLK_ClrVal();           /* CLK = 0 */

    for(i=0; i<127; i++) {
        delay_us(100);
        CLK_SetVal();       /* CLK = 1 */
        delay_us(100);
        //Sampling Pixel 2~128
            
       *ImageData=Get_Adc1(&hadc1)>>4;	 
        ImageData++;
        CLK_ClrVal();       /* CLK = 0 */
    }
    delay_us(30);
    CLK_SetVal();           /* CLK = 1 */
   	delay_us(30);
    CLK_ClrVal(); 
		/* CLK = 0 */
		 for(n=0;n<IntegrationTime;n++)   //控制曝光延时可通过改变Exposure_tim实现，规则见上文
	{
		delay_us(1);
		CLK_SetVal(); 	
		delay_us(1);
		 CLK_ClrVal();		
  }

}
void  Find_CCD_Zhongzhi(void)
{ 
		 static uint16_t i,j,k,l;
		 static uint16_t value1_max,value1_min;
	  int count=0;
	   value1_max=Pixel[0];  //动态阈值算法，读取最大和最小值
     for(i=5;i<123;i++)   //两边各去掉5个点
     {
        if(value1_max<=Pixel[i])
        value1_max=Pixel[i];
     }
	   value1_min=Pixel[0];  //最小值
     for(i=5;i<123;i++) 
     {
        if(value1_min>=Pixel[i])
        value1_min=Pixel[i];
     }
   CCD_Yuzhi=(value1_max+value1_min)/2;	  //计算出本次中线提取的阈值
		 

	 for(i = 20;i<64; i++)   //寻找   左边跳变沿
	{
		if(Pixel[i]>CCD_Yuzhi&&Pixel[i+1]>CCD_Yuzhi&&Pixel[i+2]>CCD_Yuzhi&&Pixel[i+3]<CCD_Yuzhi&&Pixel[i+4]<CCD_Yuzhi&&Pixel[i+5]<CCD_Yuzhi)
		{	
			Left=i+2;
			break;	
		}
	}
	for(k=50;k<70;k++)
	{
		if(Pixel[k]>CCD_Yuzhi)
			count++;
		if(count>18)
			{		Left_falg_Bai=1; }//左边全白
			else {Left_falg_Bai=0; }
		}
	count=0;
	 for(j = 100;j>64; j--)//寻找右边跳变沿
  {
		if(Pixel[j]<CCD_Yuzhi&&Pixel[j+1]<CCD_Yuzhi&&Pixel[j+2]<CCD_Yuzhi&&Pixel[j+3]>CCD_Yuzhi&&Pixel[j+4]>CCD_Yuzhi&&Pixel[j+5]>CCD_Yuzhi)
		{	
		  Right=j-2;
		  break;	
		}
  }
	for(l=85;l>50;l--)
	{
	if(Pixel[l]>CCD_Yuzhi)
			count++;
		if(count>30)
		{Right_falg_Bai=1; }//右边全白
		else {Right_falg_Bai=0;}
	}
	CCD_Zhongzhi=(Right+Left)/2;//计算中线位置
	if(__fabs(CCD_Zhongzhi-Last_CCD_Zhongzhi)>90)   //计算中线的偏差，如果太大
	CCD_Zhongzhi=Last_CCD_Zhongzhi;    //则取上一次的值
	CCD_Error=CCD_Zhongzhi-64;//计算误差
	CCD_Error_Temp=CCD_Zhongzhi-Last_CCD_Zhongzhi;//误差微分
  Last_CCD_Zhongzhi=CCD_Zhongzhi;  //保存上一次的偏差
	CCD_PWM=CCD_KP*CCD_Error+CCD_KD*CCD_Error_Temp ;
	if(CCD_PWM>5)
	{ CCD_PWM=5; }
	if(CCD_PWM<-5)
	{ CCD_PWM=-5; }
}

/*************************************************************************
*  函数名称：CalculateIntegrationTime
*  功能说明：计算曝光时间
*  参数说明：
*  函数返回：无
*  修改时间：2021-10-20
*  备    注：
*************************************************************************/
extern uint8_t Pixel[128];
/* 曝光时间，单位ms */

void CalculateIntegrationTime(void)
 {

/* 128个像素点的平均AD值 */
uint8_t PixelAverageValue;
/* 128个像素点的平均电压值的10倍 */
uint8_t PixelAverageVoltage;
/* 设定目标平均电压值，实际电压的10倍 */
int16_t TargetPixelAverageVoltage = 20;
/* 设定目标平均电压值与实际值的偏差，实际电压的10倍 */
int16_t PixelAverageVoltageError = 0;
/* 设定目标平均电压值允许的偏差，实际电压的10倍 */
int16_t TargetPixelAverageVoltageAllowError = 2;

    /* 计算128个像素点的平均AD值 */
    PixelAverageValue = PixelAverage(128,Pixel);
    /* 计算128个像素点的平均电压值,实际值的10倍 */
    PixelAverageVoltage = (uint8_t)((int16_t)PixelAverageValue * 25 / 194);

    PixelAverageVoltageError = TargetPixelAverageVoltage - PixelAverageVoltage;
    if(PixelAverageVoltageError < -TargetPixelAverageVoltageAllowError)
    {
      PixelAverageVoltageError = 0- PixelAverageVoltageError ;
      PixelAverageVoltageError /= 5;
      if(PixelAverageVoltageError > 10 )
         PixelAverageVoltageError = 10 ;
       IntegrationTime -= PixelAverageVoltageError;
    }
    if(PixelAverageVoltageError > TargetPixelAverageVoltageAllowError)
    { 
        PixelAverageVoltageError /= 5;
        if(PixelAverageVoltageError > 10 )
           PixelAverageVoltageError = 10 ;
        IntegrationTime += PixelAverageVoltageError;}
//  /*  */
/*    
    uart_putchar(UART0,0XAA) ;
    uart_putchar(UART0,PixelAverageVoltage) ;
    uart_putchar(UART0,PixelAverageVoltageError) ;
    uart_putchar(UART0,IntegrationTime) ;
 */   
    if(IntegrationTime <= 1)
        IntegrationTime = 1;
    if(IntegrationTime >= 100)
        IntegrationTime = 100;
		

}

/*************************************************************************
*                        
*
*  函数名称：PixelAverage
*  功能说明：求数组的均值程序
*  参数说明：
*  函数返回：无
*  修改时间：2021-10-20
*  备    注：
*************************************************************************/
uint8_t PixelAverage(uint8_t len, uint8_t *data) {
  unsigned char i;
  unsigned int sum = 0;
  for(i = 0; i<len; i++) {
    sum = sum + *data++;
  }
  return ((unsigned char)(sum/len));
}

/*************************************************************************
*                       
*
*  函数名称：SamplingDelay
*  功能说明：CCD延时程序 
*  参数说明：
*  函数返回：无
*  修改时间：2021-10-20
*  备    注：
*************************************************************************/
void SamplingDelay(void)
{
   volatile uint8_t i ;
   for(i=0;i<1;i++)
	{
    __NOP();
    __NOP();}
   
}

	
void imageDebugOut(void)
{
	printf("*YAN CCD Loading******* ");
	for (int count = 0; count < 128; count++)
	{
		printf("%d ",Pixel[count]);
	}
	HAL_Delay(300);
	printf("\n\r");
}
